/*
 *  serialize.cc
 *  wonderland-project
 *
 *  Created by Ben Nolan on 22/10/08.
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
 *
 */

#include "serialize.h"
#include "tinyxml/tinyxml.h"

#include <boost/foreach.hpp>
#include <OgreVector3.h>
#include <OgreEntity.h>
#include <OgreSceneNode.h>

namespace Wonderland{

  /* Helper functions */
  std::string vectorToString(Ogre::Vector3 v){
    std::stringstream coord;
    coord << v.x << " ";
    coord << v.y << " ";
    coord << v.z << " ";
    return coord.str();
  }

  std::string quaternionToString(Ogre::Quaternion q){
    std::stringstream coord;
    coord << q.w << " ";
    coord << q.x << " ";
    coord << q.y << " ";
    coord << q.z << " ";
    return coord.str();
  }

  TiXmlElement *entityToXml(Ogre::Entity *entity){
    TiXmlElement *el = new TiXmlElement("entity");

    el->SetAttribute("id", entity->getName().c_str());
    el->SetAttribute("src", entity->getMesh()->getName().c_str());
    
    return el;
  }

  TiXmlElement *nodeToXml(Ogre::SceneNode *node){
    TiXmlElement *elNode = new TiXmlElement("node");
    TiXmlElement *el;
    elNode->SetAttribute("id", node->getName());

    el = new TiXmlElement("translate");
    el->InsertEndChild(TiXmlText(vectorToString(node->getPosition()).c_str()));
    elNode->InsertEndChild(*el);
  
    el = new TiXmlElement("rotate");
    el->InsertEndChild(TiXmlText(quaternionToString(node->getOrientation()).c_str()));
    elNode->InsertEndChild(*el);
  
    el = new TiXmlElement("scale");
    el->InsertEndChild(TiXmlText(vectorToString(node->getScale()).c_str()));
    elNode->InsertEndChild(*el);

    // Add entities
    Ogre::SceneNode::ObjectIterator oitr = node->getAttachedObjectIterator();
    while(oitr.hasMoreElements()){
      Ogre::MovableObject *obj = oitr.getNext();
      
      if (obj->getMovableType() == (std::string)"Entity"){
        elNode->InsertEndChild(*entityToXml((Ogre::Entity*) obj));
      }
    }

    // Add child nodes
    Ogre::Node::ChildNodeIterator itr = node->getChildIterator();
    while(itr.hasMoreElements()){
      elNode->InsertEndChild(*nodeToXml((Ogre::SceneNode*) itr.getNext()));
    }

    return elNode;
  }
  
  /*
   * Main serialize function 
   *
   * We try and use the collada scene format as much as possible. This
   * means we don't reinvent the wheel, and we have a reference document.
   *
   */
  std::string Serialize(Ogre::Node *node){
    TiXmlDocument doc;

    doc.InsertEndChild(*nodeToXml((Ogre::SceneNode*) node));

    std::stringstream xml;
    xml << doc << std::endl;
    return xml.str();
  }
	
	/*
	 * Process a list of nodes
	 */
	std::string SerializeNodelist(std::list<Ogre::SceneNode *> nodelist){
		TiXmlDocument doc;
		TiXmlElement el("nodelist");
		
		BOOST_FOREACH(Ogre::SceneNode* node, nodelist){
			el.InsertEndChild(*nodeToXml((Ogre::SceneNode*) node));
		}
		
		doc.InsertEndChild(el);
		
		std::stringstream xml;
		xml << doc << std::endl;
		return xml.str();
	}
  
}